﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using RapidSalesAdminPortalAPI.DataAccess;
using RapidSalesAdminPortalAPI.Models;
using RapidSalesAdminPortalAPI.Services;
using System.Security.Cryptography.Xml;
using WebAPI.Common;
using WebAPI.Common.Attributes;
using WebAPI.Controllers;
using WebAPI.Models;
using WebAPI.Services;
using WebAPI.Util;

namespace RapidSalesAdminPortalAPI.Controllers
{
    //[Authorize]
    [Route("api/[controller]")]
    [ApiController]
    public class ProductController : ParentController
    {
        private readonly RS_AdmPortalContext _context;
        private readonly IConfiguration _configuration;
        private readonly ILogUtility _logUtility;
        private readonly ILogger _logger;
        private readonly IDataProtectorUtility _dataProtectorUntility;
        private ISoapService _soapService;

        public ProductController(RS_AdmPortalContext context, IConfiguration configuration, ILogUtility logUtility, ILogger<ProductController> logger, IDataProtectorUtility dataProtectorUntility
            , ISoapService soapService)
        {
            _context = context;
            _configuration = configuration;
            _logUtility = logUtility; // sample code for DI of common utility class
            _logger = logger;
            _dataProtectorUntility = dataProtectorUntility;
            _soapService = soapService; 
        }

        [HttpPost("GetProductList")]
        public async Task<ActionResult<ResultMsg>> GetProductList([FromBody] GetProductListRequest requestModel)
        {
            var resultMsg = new ResultMsg();
            try
            {
                IQueryable<FrIpProductEvent> paComont = _context.FrIpProductEvents.Include(x=>x.Product).Include(x=>x.Event).AsQueryable();
                if (!string.IsNullOrWhiteSpace(requestModel.Status))
                    paComont = paComont.Where(x => x.Product.Enable.ToString() == requestModel.Status);
                if (!string.IsNullOrWhiteSpace(requestModel.MatrixCellAk))
                    paComont = paComont.Where(x => x.Product.MatrixCellAk.Contains(requestModel.MatrixCellAk));
                if (!string.IsNullOrWhiteSpace(requestModel.ProductCode))
                    paComont = paComont.Where(x => x.Product.ProductCode.Contains(requestModel.ProductCode));
                if (!string.IsNullOrWhiteSpace(requestModel.ProductNameEn))
                    paComont = paComont.Where(x => x.Product.ProductNameEn.Contains(requestModel.ProductNameEn));
                if (!string.IsNullOrWhiteSpace(requestModel.TicketDescriptionEn))
                    paComont = paComont.Where(x => x.Product.TicketDescriptionEn.Contains(requestModel.TicketDescriptionEn));
                if (!string.IsNullOrWhiteSpace(requestModel.EventAk))
                    paComont = paComont.Where(x => x.Event.EventAk.Contains(requestModel.EventAk));
                if (!string.IsNullOrWhiteSpace(requestModel.EventNameEn))
                    paComont = paComont.Where(x => x.Event.EventNameEn.Contains(requestModel.EventNameEn));
                if (!string.IsNullOrWhiteSpace(requestModel.EventDescriptionEn))
                    paComont = paComont.Where(x => x.Event.EventDescriptionEn.Contains(requestModel.EventDescriptionEn));
                //if (!string.IsNullOrWhiteSpace(requestModel.ParentalGuidance))
                //    paComont = paComont.Where(x => x.ParentalGuidance.Contains(requestModel.ParentalGuidance));

                //if (!string.IsNullOrWhiteSpace(requestModel.RapidSalesSStartDate))
                //    paComont = paComont.Where(x => x.SalesPointProduct.RapidSalesStartDate > Convert.ToDateTime(requestModel.RapidSalesSStartDate));
                //if (!string.IsNullOrWhiteSpace(requestModel.RapidSalesSEndDate))
                //    paComont = paComont.Where(x => x.SalesPointProduct.RapidSalesStartDate < Convert.ToDateTime(requestModel.RapidSalesSEndDate));

                //if (!string.IsNullOrWhiteSpace(requestModel.RapidSalesEStartDate))
                //    paComont = paComont.Where(x => x.SalesPointProduct.RapidSalesEndDate > Convert.ToDateTime(requestModel.RapidSalesEStartDate));
                //if (!string.IsNullOrWhiteSpace(requestModel.RapidSalesEEndDate))
                //    paComont = paComont.Where(x => x.SalesPointProduct.RapidSalesEndDate < Convert.ToDateTime(requestModel.RapidSalesEEndDate));


                var paData = paComont.ToList().Select(x => new ProductListResponse()
                {
                    Id = x.ProductId,
                    MatrixCellAk = x.Product.MatrixCellAk,
                    ProductCode = x.Product.ProductCode,
                    ProductNameEn = x.Product.ProductNameEn,
                    ProductNameTc = x.Product.ProductNameTc,
                    ProductNameSc = x.Product.ProductNameSc,
                    TicketDescriptionEn = x.Product.TicketDescriptionEn,
                    TicketDescriptionTc = x.Product.TicketDescriptionTc,
                    TicketDescriptionSc = x.Product.TicketDescriptionSc,
                    UnitPrice = x.Product.UnitPrice,
                    EventAk = x.Event.EventAk,
                    EventNameEn = x.Event.EventNameEn,
                    EventNameTc = x.Event.EventNameTc,
                    EventNameSc = x.Event.EventNameSc,
                    EventDescriptionEn = x.Event.EventDescriptionEn,
                    Enable = x.Product.Enable,
                    MaxPurchaseQty = x.Product.MaxPurchaseQty.GetValueOrDefault(),

                }).AsQueryable();

                if (!string.IsNullOrWhiteSpace(requestModel.Field) && paComont.Count() > 0)
                    paData = DBHelper.DataSorting(paData, requestModel.Field, requestModel.Order);
                else
                    paData = DBHelper.DataSorting(paData, "CreateDate", "desc");

                var productList = await BasePageOutputExtensions.ToPagedListAsync(paData.ToList(), requestModel.Page, requestModel.PageSize);

                return resultMsg.SetResultMsg(
                     (int)ResultCode.Success,
                     HelperUtility.GetDescription(ResultCode.Success),
                     productList);//
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.Message);
                return resultMsg.SetResultMsg(
                     (int)ResultCode.ErrorOnRequestUnMarshalling,
                     HelperUtility.GetDescription(ResultCode.ErrorOnRequestUnMarshalling),
                     null);
            }
        }

        [HttpGet("GetLastUpdateTime")]
        public async Task<ActionResult<ResultMsg>> GetLastUpdateTime()
        {
            var resultMsg = new ResultMsg();
            try
            {
                var lastUpdateTime = _context.FrIpProductEvents.Include(x => x.Product).Select(x => x.Product.UpdateDate).ToList().Max();//.Select(x=>x.Product.UpdateDate)

                return resultMsg.SetResultMsg(
                     (int)ResultCode.Success,
                     HelperUtility.GetDescription(ResultCode.Success),
                     lastUpdateTime);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.Message);
                return resultMsg.SetResultMsg(
                     (int)ResultCode.ErrorOnRequestUnMarshalling,
                     HelperUtility.GetDescription(ResultCode.ErrorOnRequestUnMarshalling),
                     null);
            }
        }

        [HttpGet("{id}")]
        public async Task<ActionResult<ResultMsg>> ProductDetail(Guid id)
        {
            var resultMsg = new ResultMsg();
            try
            {
                FrIpProductEvent x = await _context.FrIpProductEvents.Include(x=>x.Product).Include(x=>x.Event).Include(x=>x.FrIpSalesPointProducts).FirstOrDefaultAsync(x => x.ProductId == id);
                if (x == null)
                {
                    return resultMsg.SetResultMsg(
                         (int)ResultCode.NoDataFound,
                         HelperUtility.GetDescription(ResultCode.NoDataFound),
                         null);
                }

                var productInfo = new ProductListResponse()
                {
                    Id = x.ProductId,
                    MatrixCellAk = x.Product?.MatrixCellAk,
                    ProductCode = x.Product.ProductCode,
                    ProductNameEn = x.Product.ProductNameEn,
                    ProductNameTc = x.Product.ProductNameTc,
                    ProductNameSc = x.Product.ProductNameSc,
                    TicketDescriptionEn = x.Product.TicketDescriptionEn,
                    TicketDescriptionTc = x.Product.TicketDescriptionTc,
                    TicketDescriptionSc = x.Product.TicketDescriptionSc,
                    UnitPrice = x.Product.UnitPrice,
                    EventAk = x.Event?.EventAk,
                    EventNameEn = x.Event.EventNameEn,
                    EventNameTc = x.Event.EventNameTc,
                    EventNameSc = x.Event.EventNameSc,
                    EventDescriptionEn = x.Event.EventDescriptionEn,
                    Enable = x.Product.Enable,
                    Thumbnail = x.Product.Thumbnail,
                    MaxPurchaseQty = x.Product.MaxPurchaseQty.GetValueOrDefault(),
                };
                var salePointIdList = x.FrIpSalesPointProducts?.Select(x => x.SalesPointId).ToList();
                if (salePointIdList != null && salePointIdList.Count > 0) {
                    productInfo.SalePointList = _context.FrIpSalesPoints.Include(x=>x.OperationArea).Where(a => salePointIdList.Contains(a.Id)).Select(a=>new SalesPointResponse()
                    {
                        Code = a.Code,
                        NameEn = a.NameEn,
                        NameTc = a.NameTc,
                        NameSc = a.NameSc,
                        DescriptionEn = a.DescriptionEn,
                        DescriptionTc = a.DescriptionTc,
                        DescriptionSc= a.DescriptionSc,
                        Exclusive = a.Exclusive,
                        Passcode = a.Passcode,
                        OperationAre = a.OperationArea.Value,
                        Enable = a.Enable
                    })?.ToList();
                }

                return resultMsg.SetResultMsg(
                     (int)ResultCode.Success,
                     HelperUtility.GetDescription(ResultCode.Success),
                     productInfo);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.Message);
                return resultMsg.SetResultMsg(
                     (int)ResultCode.ErrorOnRequestUnMarshalling,
                     HelperUtility.GetDescription(ResultCode.ErrorOnRequestUnMarshalling),
                     null);
            }
        }

        [Log("FrIpProduct", "UpdateFrIpProduct", description: "FrIpProduct/UpdateFrIpProduct", LogType: Enums.LogType.AdministratorAccountLog)]
        [HttpPut("UpdateFrIpProduct")]
        public async Task<ActionResult<ResultMsg>> UpdateFrIpProduct([FromBody] UpdateFrIpProductRequest request)
        {
            var resultMsg = new ResultMsg();
            try
            {
                if (!FrIpProductExists(request.Id))
                {
                    return resultMsg.SetResultMsg(
                     (int)ResultCode.NoDataFound,
                     HelperUtility.GetDescription(ResultCode.NoDataFound),
                     null);
                }
            
                FrIpProduct dt = await _context.FrIpProducts.Include(x=>x.FrIpProductEvents).FirstOrDefaultAsync(x => x.Id == request.Id);
                if (dt != null && !string.IsNullOrWhiteSpace(request.RapidSalesStartDate) && !string.IsNullOrWhiteSpace(request.RapidSalesEndDate)) {
                    dt.FrIpProductEvents.ToList().ForEach(x => x.FrIpSalesPointProducts.ToList().ForEach(a => {
                        a.RapidSalesStartDate = Convert.ToDateTime(request.RapidSalesStartDate);
                        a.RapidSalesEndDate = Convert.ToDateTime(request.RapidSalesStartDate);
                    }));
                }
             
                dt.Enable = request.Enable;
                //dt.RapidSalesStartDate = request.RapidSalesStartDate;
                //dt.RapidSalesEndDate = request.RapidSalesEndDate;
                dt.UpdateUser = CurrentUserId;
                dt.UpdateDate = DateTime.Now;
                _context.Entry(dt).State = EntityState.Modified;
                await _context.SaveChangesAsync();
                return resultMsg.SetResultMsg(
                  (int)ResultCode.Success,
                  HelperUtility.GetDescription(ResultCode.Success),
                  null);
            }
            catch (Exception ex)
            {
                _logger.LogError("FrIpProduct/UpdateFrIpProduct Error:" + ex.Message);
                return resultMsg.SetResultMsg(
                 (int)ResultCode.ErrorOnRequestUnMarshalling,
                 HelperUtility.GetDescription(ResultCode.UserNotFound),
                 null);
            }
        }


        [Log("FrIpProduct", "EnableFrIpProduct", description: "FrIpProduct/EnableFrIpProduct", LogType: Enums.LogType.AdministratorAccountLog)]
        [HttpPut("EnableFrIpProduct")]
        public async Task<ActionResult<ResultMsg>> EnableFrIpProduct([FromBody] EnableFrIpProductRequest requestModel)
        {
            ResultMsg resultMsg = new();
            var productList = _context.FrIpProducts.Where(x => requestModel.ids.Contains(x.Id.ToString())).ToList();
            if (productList == null || productList.Count <= 0)
            {
                return resultMsg.SetResultMsg(
               (int)ResultCode.UserNotFound,
               HelperUtility.GetDescription(ResultCode.UserNotFound),
               null);
            }
            foreach (var product in productList)
            {
                product.Enable = requestModel.enable;
            }
            await _context.SaveChangesAsync();
            return resultMsg.SetResultMsg(
                (int)ResultCode.Success,
                HelperUtility.GetDescription(ResultCode.Success),
                null);
        }

        [NonAction]
        private bool FrIpProductExists(Guid id)
        {
            return _context.FrIpProducts.Any(e => e.Id == id);
        }
    }
}
